home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 March
/
EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso
/
cd-sup
/
updatecopy
/
source
/
updatecopy.e
Wrap
Text File
|
1999-01-01
|
26KB
|
841 lines
/* UpDateCopy.e
** Copies multiple files/directories to one destination.
** Not existing directories are created.
** Already existing files are only replaced by newer ones
** (UpDateCopy first checks for versions-string and then
** for dates).
**
** $VER: UpDateCopy.e 0.52 (21.02.97)
**
** This program is Cardware. If you use it you should send an Email to
** the author. Also small presents are very welcome.
** You may use this sourcefile or parts of it freely in your programs.
** But please do not spread a modified version under this name (UpDateCopy).
** For Bugreports, ideas or anything else send a Email to:
** ss37@irz.inf.tu-dresden.de
**
** Sven Steiniger, 1996, 1997
**
** Fold-start: ->// ""
** Fold-stop: ->\\
**
** History:
** 0.52: - improved SMARTINFO-option
** 0.51: - removed bug of version-scan-routines
** 0.50: - added FAST-option
** 0.49: - added SMARTINFO option
** - added wildcard-check. Now you can also use '*' as wildcard and
** you can also pass devices as sources (eq. ram:)
** 0.48: - used exthelp-feature OF ReadArgs()
** - no longer needs 'c:copy'-command. Implemented an own routine.
** 0.47: - file was not closed before SetProtection()/SetFileDate()
** 0.46: - added PAPF-option -> archive protection flag is not changed
** 0.45: - added CLONE-option -> Datestamp is copied
** 0.44: - removed a unnecessary module. Saves 1K of executable size!
** - removed unnecessary ExamineFH()
** - now file gets only examined if really necessary
** - optimized a bit
** - FIXED: TESTMODE was buggy -> Directories were still created.
** 0.43: - add new option TESTMODE; dont copy/replace files
** 0.42: - add new option NODATECHECK; dont compare datestamps
** 0.41: - replaced ALL reads/writes by fread/fwrite
** 0.40: - first PUBLIC release
*/
OPT OSVERSION=37
OPT REG=5
MODULE 'dos/dos','dos/dosasl','dos/dostags','dos/rdargs'
RAISE "MEM" IF String()=NIL,
"addp" IF AddPart()=DOSFALSE,
"^C" IF CtrlC()=TRUE,
"copy" IF FileLength()=-1,
"MEM" IF AllocDosObject()=NIL,
"fatt" IF SetProtection()=DOSFALSE,
"fatt" IF SetComment()=DOSFALSE,
"fatt" IF SetFileDate()=DOSFALSE
CONST MAXPATH=255, -> Maximum path length
SPACEADD=3, -> Number of spaces per indent
SAFETYBYTES=100, -> Maximum length of versionstring
BIGFILEMEM=100000 -> Files bigger than that are not read
-> completly into memory
CONST PATHLENGTH=MAXPATH-1,
BIGFILESIZE=BIGFILEMEM-SAFETYBYTES
ENUM PDIR_Error,
PDIR_Skipped,
PDIR_Created
ENUM PFILE_Error,
PFILE_Skipped,
PFILE_Copied,
PFILE_Replaced
DEF frompath[MAXPATH]:STRING, -> actual sourcepath
fromlist:PTR TO LONG, -> pointer to array of sourcestrings
topath[MAXPATH]:STRING, -> destinationpath
doinfo, -> should we write informations ?
recursiv, -> scan recursively through subdirectories ?
ignoreprotection, -> clear delete-protection ?
checkversion, -> compare version-strings ?
checkdates, -> compare datestamps ?
testmode, -> test modus ? (do not copy/replace files)
clone, -> copy datestamp ?
cleararchivebit, -> clear archivebit OF copied file
smartinfo, -> only display copied/replaced files
fastdisplay, -> no linefeed
dirlock=NIL -> PTR TO lock-structure OF destination path
PROC main() HANDLE
->// "main()"
DEF rdargs=NIL,
myargs:PTR TO LONG,
template,
myrdargs=NIL:PTR TO rdargs,
exthelp[1000]:STRING
/* Initialize argument-array */
myargs:=[
NIL, -> fromlist
NIL, -> destination path
FALSE, -> ~showinfo
FALSE, -> scan recursiv throuhg subdirectories
FALSE, -> ignore protectionbits
FALSE, -> deep scan
FALSE, -> ~compare datestamps
FALSE, -> testmode
FALSE, -> clone
FALSE, -> preserve archive protection flag
FALSE, -> smartinfo
FALSE -> fastdisplay
]:LONG
myrdargs:=AllocDosObject(DOS_RDARGS,NIL)
StrCopy(exthelp, '\n'+
' UpDateCopy v0.52\n'+
' -----------------\n'+
' Copy files and directories.\n'+
' Not existing directories are created and\n'+
' already existing files are only replaced\n'+
' by newer ones. Allows pattern-matching and\n'+
' multiple sourcedirectories/files.\n\n'+
'Sven Steiniger, 1996, 1997\n',
ALL)
StrAdd(exthelp, '\n'+
' FROM - source directory/file(s)\n'+
' TO - destination directory\n'+
' QUIET - no outputs\n'+
' ALL - scans through subdirectories recursively\n'+
' FORCE - ignore delete-protectionbit\n'+
' DEEP - compare version-strings\n'+
' NODATECHECK - don''t compare datestamps\n'+
' TESTMODE - neither copy/replace files nor create directories\n'+
' CLONE - copy datestamp\n'+
' PAPF - don''t clear the archive protection flag\n'+
' SMARTINFO - only displays copied/replaced files\n'+
' FAST - fast output. No linefeeds\n',
ALL)
myrdargs.exthelp:=exthelp
/* Parse Commandline */
IF rdargs:=ReadArgs(template:='FROM/M,TO/A,QUIET/S,ALL/S,FORCE/S,DEEP/S,'+
'NDC=NODATECHECK/S,TESTMODE/S,CLONE/S,PAPF/S,'+
'SMARTINFO/S,FAST/S',
myargs,myrdargs)
/* Copy Datas to global variables */
fromlist := myargs[0]
StrCopy(topath,myargs[1],ALL)
doinfo := Not(myargs[2])
recursiv := myargs[3]
ignoreprotection := myargs[4]
checkversion := myargs[5]
checkdates := Not(myargs[6])
testmode := myargs[7]
clone := myargs[8]
cleararchivebit := Not(myargs[9])
smartinfo := myargs[10]
fastdisplay := myargs[11]
IF fromlist=NIL THEN Throw("ARGS",'No source specified.')
init_arguments()
IF doinfo
PrintF('Updating files to "\s".\n',topath)
IF testmode THEN PrintF('** Testmode **\n')
ENDIF
IF fastdisplay
PrintF('\n')
smartinfo:=FALSE
ENDIF
WHILE fromlist[] -> 'fromlist' is array of string-pointers
StrCopy(frompath,fromlist[]++,ALL) -> copy the string and increment 'fromlist'
checkWildCard(frompath)
scan_directory(frompath,'',1) -> then process this directory
ENDWHILE
ENDIF
EXCEPT DO -> Cleanup
IF fastdisplay THEN reportLine(0,'',NIL,NIL)
free_arguments()
IF rdargs THEN FreeArgs(rdargs)
FreeDosObject(DOS_RDARGS,myrdargs)
IF exception
/* Print error description */
PrintF('Error: ')
SELECT exception
CASE "MEM" ; PrintF('Not enough memory.\n')
CASE "addp" ; PrintF('Path too long !?\n')
CASE "^C" ; PrintF('User abort.\n')
CASE "copy" ; PrintF('Could not copy file.\n')
CASE "open" ; PrintF('Could not open file.\n')
CASE "anly" ; PrintF('Could not analyse file.\n')
CASE "fatt" ; PrintF('Could not set file attributes.\n')
DEFAULT ; PrintF('\s\n',exceptioninfo)
ENDSELECT
ELSE
PrintF('Finished.\n')
ENDIF
CleanUp(exception)
ENDPROC
->\\
versionstring: CHAR '$VER: UpDateCopy 0.52 (21.02.97)',0
/* checks the arguments provied by user
*/
PROC init_arguments()
->// "init_arguments()"
IF (dirlock:=Lock(topath,SHARED_LOCK))=NIL -> check if destination
Throw("dir",'Could not lock destination directory') -> directory exists
ENDIF
/* Enable Version Check if datestamp-check is switch off */
IF checkdates=FALSE THEN checkversion:=TRUE
ENDPROC
->\\
/* handles so special cases with wildcards
** Parameter:
** file - file/dir to be checked
*/
PROC checkWildCard(file:PTR TO CHAR)
->// "checkWildCard"
DEF len
len:=StrLen(file)
IF file[len-1]="*"
-> replace '*'-wildcard by '#?'
CopyMem('#?',file+len-1,3)
ELSEIF file[len-1]=":"
-> it's an device. Therefore add wildcard
CopyMem('#?',file+len,3)
ENDIF
ENDPROC
->\\
/* Cleanup datas allocated during init_arguments
*/
PROC free_arguments()
->// "free_arguments()"
UnLock(dirlock) -> Unlock destination directory
ENDPROC
->\\
/* Scans a directory and copies files/creates subdirectories
** Parameter:
** directory - name of directory to be scanned
** path - the current delta path
** depth - recursion level
** Example:
** The source path is "esource:src".
** 'directory' is "esource:src/tools/file".
** Then 'path' have to be "tools/file".
*/
PROC scan_directory(directory,path,depth) HANDLE
->// "scan_directory()"
DEF info:PTR TO fileinfoblock,
anchor=NIL:PTR TO anchorpath,
error,
fullpath,
mypath[MAXPATH]:STRING,
length
/* Create and initialize anchor structure needed for
** scanning through directory.
** This structure has no fixed size.
*/
anchor:=NewR(SIZEOF anchorpath+MAXPATH)
anchor.strlen:=PATHLENGTH
-> Get start of string
fullpath:=anchor+SIZEOF anchorpath
error:=MatchFirst(directory,anchor)
WHILE error=DOSFALSE
CtrlC()
info:=anchor.info -> get fileinfoblock
IF info.direntrytype>0 -> is it a directory ?
StrCopy(mypath,path,ALL) -> init new delta path
AddPart(mypath,info.filename,PATHLENGTH) -> including new subdirectory
process_directory(fullpath,info,mypath, -> knows what to do with this
depth*SPACEADD) -> directory
IF recursiv -> scan subdirectories ?
length:=StrLen(fullpath)
IF (length+5)<MAXPATH
CopyMem('/#?',fullpath+length,4) -> add pattern matching
ENDIF
scan_directory(fullpath,mypath,depth+1) -> call our self with new subdirectory
fullpath[length]:=0 -> remove pattern matching
ENDIF
ELSE
process_file(fullpath,info,path, -> knows what to do with it
depth*SPACEADD)
ENDIF
error:=MatchNext(anchor) -> Next entry
ENDWHILE
EXCEPT DO
IF anchor
MatchEnd(anchor) -> Clean up
Dispose(anchor)
ENDIF
ReThrow()
ENDPROC
->\\
/* takes care of fastdisplay-option
*/
PROC reportLine(spaceanz,fmtstr,arg1,arg2)
IF fastdisplay
PrintF([141,$1b,"[","M",0]:CHAR)
spaceanz:=SPACEADD
ENDIF
WHILE spaceanz-->=0 DO FputC(stdout," ")
PrintF(fmtstr,arg1,arg2) -> Write directory name & status
PrintF('\n')
ENDPROC
/* Prints a directory status.
** Parameter:
** spaces - number of leading spaces
** status - status (PDIR_Error, PDIR_Skipped, PDIR_Created)
** path - directory path
*/
PROC printDirStatus(spaces,status,path)
->// "printDirStatus()"
DEF stri
IF doinfo
SELECT status
CASE PDIR_Created ; stri:='created'
CASE PDIR_Skipped ; IF smartinfo THEN RETURN -> don't display skipped dirs with smartinfo
stri:='skipped'
DEFAULT ; stri:='Error!!'
ENDSELECT
reportLine(spaces,'\e[1m\s\e[0m..\s',path,stri) -> Write directory name & status
ENDIF
ENDPROC
->\\
/* Process an directory. If it doesnt exists it will be created
** Parameter:
** directory - full path of source directory
** info - pointer to fileinfoblock of source directory
** path - delta path of directory
*/
PROC process_directory(directory,info:PTR TO fileinfoblock,path,spaces)
->// "process_directory()"
DEF stri[MAXPATH]:STRING,
lock
StrCopy(stri,topath,ALL)
AddPart(stri,path,PATHLENGTH) -> thats the destion-directory
IF lock:=Lock(stri,SHARED_LOCK) -> Exists this Directory ?
printDirStatus(spaces, PDIR_Skipped, path)
UnLock(lock) -> Unlock directory
ELSEIF testmode -> Don't create directory in testmode
printDirStatus(spaces, PDIR_Created, path) -> but write out a info
ELSEIF lock:=CreateDir(stri) -> Create the directory
printDirStatus(spaces, PDIR_Created, path)
UnLock(lock) -> No erros, unlock directory
copyAdditionalInformations(stri,info)
ELSE -> Directory could not be created
printDirStatus(spaces, PDIR_Error, path) -> as it does not exists before
Throw("dir",'Could not create directory') -> something went wrong
ENDIF
ENDPROC
->\\
/* Prints a file status.
** Parameter:
** spaces - number of leading spaces
** status - status (PFILE_Error, PFILE_Skipped, PFILE_Created, PFILE_Skipped)
** file - filename
*/
PROC printFileStatus(spaces,status,file)
->// "printFileStatus()"
DEF stri
IF doinfo
SELECT status
CASE PFILE_Copied ; stri:='copied'
CASE PFILE_Replaced ; stri:='replaced'
CASE PFILE_Skipped ; IF smartinfo THEN RETURN -> don't display skipped dirs with smartinfo
stri:='skipped'
DEFAULT ; stri:='Error!!'
ENDSELECT
reportLine(spaces,'\s..\s',file,stri) -> Write file status
ENDIF
ENDPROC
->\\
/* Processes an file. If it does not exists or is newer it is copied.
** Parameter:
** file - full source filename (include path)
** info - ptr to fileinfoblock of sourcefile
** path - deltapath to directory (exclude filename !)
*/
PROC process_file(file,info:PTR TO fileinfoblock,path,spaces) HANDLE
->// "process_file()"
DEF stri[MAXPATH]:STRING,
filepath[MAXPATH]:STRING,
fh=NIL,
toinfo=NIL:PTR TO fileinfoblock,
result=0,
frombuf=NIL
StrCopy(filepath,path,ALL) -> create deltapath
AddPart(filepath,info.filename,PATHLENGTH) -> inclusive filename
StrCopy(stri,topath,ALL) -> create full destination
AddPart(stri,filepath,PATHLENGTH) -> filepath
IF fh:=Open(stri,MODE_OLDFILE) -> Open destinationfile
IF checkversion THEN result,frombuf:=compareversion(file,stri)
IF checkdates AND (result=0)
/* Fileinfoblock have to be LONGWORD-aligned therefore
** use dos.library to create this
*/
toinfo:=AllocDosObject(DOS_FIB,NIL)
-> fill fileinfoblock
IF ExamineFH(fh,toinfo)=DOSFALSE THEN Throw("file",'Could not examine file ?!')
/* Compare versionstrings was either not specified by user
** or was not successfull. Therefore Compare filedates if
** the user want it.
*/
result:=CompareDates(toinfo.datestamp,info.datestamp)
ENDIF
IF result>0 -> fromfile newer than tofile ?
Close(fh) ; fh:=NIL -> close destination
IF ignoreprotection THEN SetProtection(stri,0) -> Clear protectionflags
-> if specified
copyfile(file,info,stri,frombuf) -> copy the file
printFileStatus(spaces, PFILE_Replaced, filepath)
ELSE
printFileStatus(spaces, PFILE_Skipped, filepath)
ENDIF
ELSE -> destination does not exists
copyfile(file,info,stri) -> copy file
printFileStatus(spaces, PFILE_Copied, filepath)
ENDIF
EXCEPT DO -> Cleanup
/* compareversion() may return the contents of the
** sourcefile. We must free this buffer
*/
IF frombuf THEN Dispose(frombuf)
IF toinfo THEN FreeDosObject(DOS_FIB,toinfo)
IF fh THEN Close(fh)
IF exception THEN printFileStatus(spaces, PFILE_Error, filepath)
ReThrow()
ENDPROC
->\\
/* Copies a file. For files >BIGFILESIZE Bytes c:copy is
** used.
** Parameter:
** fromfile - full path of sourcefile
** tofile - full path of destinationfile
** frombuf - Contents of sourcefile. If NIL then sourcefile
** is read
*/
PROC copyfile(fromfile,frominfo:PTR TO fileinfoblock,tofile,frombuf=NIL) HANDLE
->// "copyfile()"
DEF fhfrom=NIL,
fhto=NIL,
length,
buf=NIL,
steplength,actlength
IF testmode THEN RETURN
IF (fhfrom:=Open(fromfile,OLDFILE)) AND -> open sourcefile
(fhto:=Open(tofile,NEWFILE)) -> open destinationfile
IF (length:=FileLength(fromfile))>BIGFILESIZE
/* Files >BIGFILESIZE are not read completly into memory but in parts
** of BIGFILESIZE Bytes.
*/
/* Alloc new buffer */
buf:=NewR(BIGFILESIZE)
/* steplength is the length of the current block to be read */
/* actlength is the position within the file */
steplength:=actlength:=BIGFILESIZE
REPEAT
/* Read next block to buffer. If steplength<0 then EOF is reached */
IF steplength>0
IF Fread(fhfrom,buf,steplength,1)<1 THEN Raise("copy")
ENDIF
/* Write buffer to destinationfile */
IF Fwrite(fhto,buf,steplength,1)<1 THEN Raise("copy")
IF (actlength:=actlength+BIGFILESIZE)>length
steplength:=length-(actlength-BIGFILESIZE)
ENDIF
/* Read until version-string was found or EOF */
UNTIL steplength<=0
ELSE
IF frombuf -> we already know the
-> contents of the sourcefile
/* Write buffer to destinationfile */
IF Fwrite(fhto,frombuf,length,1)<1 THEN Raise("copy")
ELSE
buf:=NewR(length) -> alloc new buffer
/* Read sourcefile into buffer */
IF Fread(fhfrom,buf,length,1)<1 THEN Raise("copy")
/* Write buffer TO destinationfile */
IF Fwrite(fhto,buf,length,1)<1 THEN Raise("copy")
ENDIF
ENDIF
ELSE -> There went something wrong
Raise("copy")
ENDIF
EXCEPT DO
IF buf THEN Dispose(buf)
IF fhfrom THEN Close(fhfrom)
IF fhto THEN Close(fhto)
ReThrow()
/* Everything went ok. Copy comment, protection flags etc. */
copyAdditionalInformations(tofile,frominfo)
ENDPROC
->\\
/* Copies extra informations like protectionbits, comment etc.
** 'name' must be a valid File- or Directory path
** 'info' is the fileinfoblock of the original file/directories
** (the dates are copied from it)
**
** Note: the file may not be opened or locked!
*/
PROC copyAdditionalInformations(name,info:PTR TO fileinfoblock)
->// "copyAdditionalInformations()"
DEF protection
/* Clear protectionbit (or not) */
protection:=info.protection
IF cleararchivebit THEN protection:=protection AND Not(FIBF_ARCHIVE)
SetProtection(name,protection) -> Copy protection bits
SetComment(name,info.comment) -> Copy comment
/* Copy datestamp if clone option is activated */
IF clone THEN SetFileDate(name,info.datestamp)
ENDPROC
->\\
/* Compares the version-strings of two files
** Parameter:
** fromfile - full path of sourcefile
** tofile - full path of destinationfile
**
** Returns
** -1 if tofile-version>fromfile-version
** 0 if =
** 1 if <
** *AND* the contents of the sourcefile or NIL
*/
PROC compareversion(fromfile,tofile) HANDLE
->// "compareversion()"
DEF buffer=NIL:PTR TO CHAR,
version1,base1,
version2,base2
version2,base2,buffer:=getVersionOfFile(tofile)
/* We dont need the destination contents. Therefore delete buffer
*/
IF buffer
Dispose(buffer)
buffer:=NIL
ENDIF
/* if version is -1 then no version-string was found */
IF version2=-1 THEN RETURN 0,NIL
version1,base1,buffer:=getVersionOfFile(fromfile)
IF version1=-1 THEN RETURN 0,buffer
/* Compare the version, reversion of source/destionation
** multiply with other base to get same number of signifant numbers
*/
RETURN IF (version2*base1)>=(version1*base2) THEN -1 ELSE 1,buffer
EXCEPT -> Cleanup
IF buffer THEN Dispose(buffer)
ReThrow()
ENDPROC
->\\
/* Gets the version-number of a file
** Parameter:
** filename - full path of file
** Returns the version, base and a buffer with the contents of the file
** (description for version,base see getversion())
** buffer may be NIL if file was to large
*/
PROC getVersionOfFile(filename) HANDLE
->// "getVersionOfFile()"
DEF fh=NIL,
buffer=NIL:PTR TO CHAR,
version,base,
steplength,filelength,actlength
IF fh:=Open(filename,OLDFILE)
filelength:=FileLength(filename)
IF filelength>BIGFILEMEM
/* Files >BIGFILESIZE are not read completly into memory but in parts
** of BIGFILESIZE Bytes.
** As we may skip a versionstring the last SAFETYBYTES are copied
** to start of new BIGFILESIZE block everytime.
*/
/* Alloc new buffer and read filecontents into it */
buffer:=NewR(BIGFILEMEM)
IF Fread(fh,buffer,BIGFILEMEM,1)<1 THEN Raise("anly")
/* steplength is the length of the current block to be read */
steplength:=BIGFILESIZE
/* actlength is the position within the file */
actlength:=BIGFILEMEM
REPEAT
/* Get version. If version=-1 then read next block */
version,base:=getversion(buffer,steplength+SAFETYBYTES)
IF version=-1
/* The version-string was maybe at the end of buffer
** and therfore skipped. Copy the last SAFETYBYTES bytes
** to start of buffer to not lose the version-string.
*/
CopyMem(buffer+steplength,buffer,SAFETYBYTES)
/* Increase actlength. If actlength is greater than filelength
** then set steplength to the number of bytes left.
*/
actlength:=actlength+BIGFILESIZE
IF actlength>filelength
steplength:=filelength-(actlength-BIGFILESIZE)
ENDIF
/* Read next block to buffer. If steplength<0 then EOF is reached */
IF steplength>0
IF Fread(fh,buffer+SAFETYBYTES,steplength,1)<1 THEN Raise("anly")
ENDIF
ENDIF
/* Read until version-string was found or EOF */
UNTIL (version<>-1) OR (steplength<=0)
Dispose(buffer)
buffer:=NIL
ELSE
/* We have got a small file. Load it completly into memory.
** Alloc new buffer and read filecontents into it
*/
buffer:=NewR(filelength)
IF Fread(fh,buffer,filelength,1)<1 THEN Raise("anly")
/* get versions and reversion of sourcefile */
version,base:=getversion(buffer,filelength)
ENDIF
/* We dont need the filehandle any longer */
Close(fh)
fh:=NIL
ELSE
Raise("open")
ENDIF
EXCEPT
IF fh THEN Close(fh)
IF buffer THEN Dispose(buffer)
ReThrow()
ENDPROC version,base,buffer
->\\
/* Search for a version-string in a file
** Parameter:
** buffer - Contents of file
** bufferlength - length of buffer in bytes
** Returns version,base
** if no version-string was found then -1 is returned as version
** Example: version=81259, base=10000 means
** Versionnumber is 81259/10000=8.1259
*/
PROC getversion(buffer:PTR TO CHAR,bufferlength)
->// "getversion()"
DEF version=-1:REG,base:REG
MOVEA.L buffer,A0 -> A0..buffer
MOVE.L bufferlength,D0 -> D0..bufferlength
SUBQ.L #1,D0
MOVE.B #"$",D1
MOVE.L #"VER:",D2
gv_search_loop:
SUBQ.L #1,D0
BLT.W gv_ende -> bufferend reached ?
CMP.B (A0)+,D1
BNE.S gv_search_loop -> Found a "$" ?
CMP.L (A0),D2 -> Yes, then next characters="VER:"
BNE.S gv_search_loop
SUBQ.L #4,D0 -> We have found a version-string
BLT.S gv_ende
ADDQ.L #4,A0 -> skip "VER:"
MOVE.B #" ",D1
gv_skipspaces1: -> skip all spaces before programname
SUBQ.L #1,D0
BLT.S gv_ende -> bufferend reached ?
CMP.B (A0)+,D1
BEQ.S gv_skipspaces1
ADDQ.L #1,D0 -> all spaces skipped; we have gone
SUBQ.L #1,A0 -> one step too far.
gv_skipname: -> skip programname
SUBQ.L #1,D0
BLT.S gv_ende -> bufferend reached ?
CMP.B (A0)+,D1
BNE.S gv_skipname
ADDQ.L #1,D0 -> go one step back
SUBQ.L #1,A0
gv_skipspaces2: -> skip spaces before version-number
SUBQ.L #1,D0
BLT.S gv_ende -> bufferend reached ?
CMP.B (A0)+,D1
BEQ.S gv_skipspaces2
ADDQ.L #1,D0 -> go one step back
SUBQ.L #1,A0
MOVEQ #0,version
MOVE.B #".",D1
MOVEQ #0,D2
gv_getversion1: -> get version until we found a "."
SUBQ.L #1,D0
BLT.S gv_ende -> bufferend reached ?
MOVE.B (A0)+,D2
SUBI.L #"0",D2 -> Transform character "0".."9" into number
MULU.W #10,version -> version:=version*10
ADD.L D2,version -> +number
CMP.B (A0),D1
BNE.S gv_getversion1
SUBQ.L #1,D0 -> skip "."
ADDQ.L #1,A0
MOVE.B #" ",D1
MOVEQ #1,base
gv_getversion2: -> get reversion
SUBQ.L #1,D0
BLT.S gv_ende -> bufferend reached ?
MOVE.B (A0)+,D2
SUBI.L #"0",D2 -> Transform character "0".."9" into number
MULU.W #10,version -> version:=version*10
MULU.W #10,base -> base:=base*10
ADD.L D2,version -> +number
CMP.B (A0),D1
BNE.S gv_getversion2
gv_ende:
ENDPROC version,base
->\\